package com.cskaoyan.service;

import com.cskaoyan.bean.po.System;
import com.cskaoyan.bean.po.SystemExample;
import com.cskaoyan.bean.vo.ExpressConfigVO;
import com.cskaoyan.bean.vo.MallConfigVO;
import com.cskaoyan.bean.vo.OrderConfigVO;
import com.cskaoyan.bean.vo.WxConfigVO;
import com.cskaoyan.mapper.SystemMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * @author karlfu
 * @since 2022/06/06 10:47
 */

@Service
public class ConfigServiceImpl implements ConfigService {
    @Autowired
    SystemMapper systemMapper;

    @Override
    public MallConfigVO queryMallConfig() {
        MallConfigVO mallConfigVO = new MallConfigVO();

        getConfig(mallConfigVO);

        return mallConfigVO;
    }

    @Override
    public ExpressConfigVO queryExpressConfig() {
        ExpressConfigVO expressConfigVO = new ExpressConfigVO();

        getConfig(expressConfigVO);

        return expressConfigVO;
    }

    @Override
    public OrderConfigVO queryOrderConfig() {
        OrderConfigVO orderConfigVO = new OrderConfigVO();

        getConfig(orderConfigVO);

        return orderConfigVO;
    }

    @Override
    public WxConfigVO queryWxConfig() {
        WxConfigVO wxConfigVO = new WxConfigVO();

        getConfig(wxConfigVO);

        return wxConfigVO;
    }

    @Override
    public void updateMallConfig(MallConfigVO mallConfigBO) {
        setConfig(mallConfigBO);
    }

    @Override
    public void updateExpressConfig(ExpressConfigVO expressConfigBO) {
        setConfig(expressConfigBO);
    }

    @Override
    public void updateOrderConfig(OrderConfigVO orderConfigBO) {
        setConfig(orderConfigBO);
    }

    @Override
    public void updateWxConfig(WxConfigVO wxConfigBO) {
        setConfig(wxConfigBO);
    }

    private void setConfig(Object configBO) {
        List<String> allFieldsNames = getAllFieldsNames(configBO);
        SystemExample example = new SystemExample();
        for (String keyName : allFieldsNames) {
            SystemExample.Criteria criteria = example.createCriteria();
            Class<?> clazz = configBO.getClass();

            String keyValue = null;
            try {
                Field field = clazz.getDeclaredField(keyName);
                field.setAccessible(true);
                keyValue = ((String) field.get(configBO));
            } catch (NoSuchFieldException | IllegalAccessException e) {
                e.printStackTrace();
            }

            System record = new System();
            record.setKeyValue(keyValue);

            criteria.andKeyNameEqualTo(keyName);
            systemMapper.updateByExampleSelective(record, example);

            example.clear();
        }
    }

    private void getConfig(Object configVO) {
        List<String> allFieldsNames = getAllFieldsNames(configVO);
        SystemExample example = new SystemExample();
        for (String keyName : allFieldsNames) {
            SystemExample.Criteria criteria = example.createCriteria();

            criteria.andKeyNameEqualTo(keyName);
            example.setDistinct(true);
            String result = systemMapper.selectKeyValueByExample(example);

            String methodName = "set".concat(StringUtils.capitalize(keyName));

            Class<?> clazz = configVO.getClass();
            Method method = null;

            try {
                method = clazz.getMethod(methodName, String.class);
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }

            try {
                if (method != null) {
                    method.invoke(configVO, result);
                }
            } catch (IllegalAccessException | InvocationTargetException e) {
                e.printStackTrace();
            }

            example.clear();
        }
    }

    private List<String> getAllFieldsNames(Object obj) {
        Field[] fields = obj.getClass().getDeclaredFields();
        List<String> list = new ArrayList<>();
        for (Field field : fields) {
            //设置是否允许访问，不是修改原来的访问权限修饰词。
            field.setAccessible(true);
            String name = field.getName();
            list.add(name);
        }
        return list;
    }
}
